package com.example.elasticsearch;

import com.example.elasticsearch.entity.Goods;
import com.example.elasticsearch.mapper.GoodsMapper;
import com.example.elasticsearch.mapper.GoodsRepository;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.range.ParsedDateRange;
import org.elasticsearch.search.aggregations.bucket.range.ParsedRange;
import org.elasticsearch.search.aggregations.bucket.range.Range;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.ParsedAvg;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilterBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 必须添加类描述
 *
 * @author HTJT
 * @date 2023/3/7 15:11
 * @version 1.0
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class subSubAgg {

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsRepository goodsRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 根据商品分类聚合，获取每个商品类的平均价格，并且在商品分类聚合之上子聚合每个品牌的平均价格
     */
    @Test
    public void subSubAgg() {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        // 注意这里聚合写的位置不要写错,很容易搞混,错一个括号就不对了
        queryBuilder.addAggregation(
                AggregationBuilders.terms("categoryNameAgg").field("categoryName")
                        .subAggregation(AggregationBuilders.avg("categoryNameAvgPrice").field("price"))
                        .subAggregation(AggregationBuilders.terms("brandNameAgg").field("brandName")
                                .subAggregation(AggregationBuilders.avg("brandNameAvgPrice").field("price"))));

        SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), Goods.class, IndexCoordinates.of("goods"));

        // 获取聚合信息
        Aggregations aggregations = searchHits.getAggregations();
        assert aggregations != null;
        ParsedStringTerms categoryNameAgg = aggregations.get("categoryNameAgg");

        //获取总记录数
        System.out.println("totalHits = " + searchHits.getTotalHits());

        //获取值返回
        for (Terms.Bucket bucket : categoryNameAgg.getBuckets()) {

            // 获取聚合后的分类名称
            String categoryName = bucket.getKeyAsString();
            // 获取聚合命中的文档数量
            long docCount = bucket.getDocCount();
            // 获取聚合后的分类的平均价格,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象
            ParsedAvg avgPrice = bucket.getAggregations().get("categoryNameAvgPrice");

            System.out.println(categoryName + "======" + avgPrice.getValue() + "======" + docCount);

            ParsedStringTerms brandNameAgg = bucket.getAggregations().get("brandNameAgg");
            for (Terms.Bucket brandeNameAggBucket : brandNameAgg.getBuckets()) {
                // 获取聚合后的品牌名称
                String brandName = brandeNameAggBucket.getKeyAsString();

                // 获取聚合后的品牌的平均价格,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象
                ParsedAvg brandNameAvgPrice = brandeNameAggBucket.getAggregations().get("brandNameAvgPrice");

                System.out.println("   " + brandName + "======" + brandNameAvgPrice.getValue());
            }
        }
    }

}
